﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using AEM.Data.DAL;
using AEM.Utils;

namespace AEM.Data
{
    public delegate void SerialPortDataReceivedEventHandler(object sender, SerialDataEventArgs e);
    public delegate void SameDataEventHandler(object sender, SameDataEventArgs e);

    /// <summary>
    /// COM接收的完整数据
    /// </summary>
    public class SerialDataEventArgs : EventArgs
    {
        public Model.LiftInfo LiftInfo { get; set; }
        /// <summary>
        /// 电梯编号
        /// </summary>
        public int LiftNum { get; set; }
        /// <summary>
        /// 数据字节：Data(1)- Data(m),m<=300
        /// </summary>
        public StatusData Data { get; set; }
        /// <summary>
        /// 状态代码
        /// </summary>
        public string StatusCode { get; set; }
        /// <summary>
        /// 服务器窗口显示数据,n<=32
        /// </summary>
        public int ServerData { get; set; }
        /// <summary>
        /// 开关门次数统计
        /// </summary>
        public int Door { get; set; }
        /// <summary>
        /// 运行次数
        /// </summary>
        public int Run { get; set; }
        /// <summary>
        /// 楼层显示
        /// </summary>
        public string FloorShow { get; set; }
        /// <summary>
        /// 绝对楼层 1---N L1；以最低层为第1层向上计数到N层
        /// </summary>
        public int Floor { get; set; }
        /// <summary>
        /// 地震 true有效,false无效   N1的第0位
        /// </summary>
        public bool Earthquake { get; set; }
        /// <summary>
        /// 停止 true有效,false无效   N1的第1位
        /// </summary>
        public bool Stop { get; set; }
        /// <summary>
        /// 急停 true有效,false无效   N1的第2位
        /// </summary>
        public bool Estop { get; set; }
        /// <summary>
        /// 待机 true有效,false无效  
        /// </summary>
        public bool Standby { get; set; }

        public List<byte> SerialDataRecieved { get; set; }

        public bool IsRepeat { get; set; }
        /// <summary>
        /// 信息接收时间
        /// </summary>
        public DateTime TimeRecieved { get; set; }

        public SerialDataEventArgs()
        {
            this.TimeRecieved = DateTime.Now;
        }

        public SerialDataEventArgs(byte[] buf, string type)
        {
            this.TimeRecieved = DateTime.Now;
            string datanow = buf.toString<byte>();
            int _liftnum = -1;
            if (type == "ft")
            {
                _liftnum = buf[0];
            }
            else
            {
                _liftnum = buf[2];
            }
            RecievedTempLog _lastdata = (from s in Config.lastData
                                         where s.LiftNum == _liftnum
                                         select s).FirstOrDefault();
            if (null != _lastdata)
            {
                this.IsRepeat = false;
                if (_lastdata.SerialDataRecieved.Equals(datanow))//重复状态
                {
                    ReadDataFromLog(_lastdata.Data);
                    this.IsRepeat = true;
                    //return;
                    //SameDataEvent.Invoke(this, new SameDataEventArgs(bytes[2]));
                }
                _lastdata.LiftNum = _liftnum;
                _lastdata.SerialDataRecieved = datanow;
            }
            List<byte> buffer = new List<byte>(buf.Length);
            buffer.AddRange(buf);
            ReadDataFromLog(new SerialDataEventArgs(buffer, type));
            if (null != _lastdata)
                _lastdata.Data = this;
            else
            {
                Config.lastData.Add(new RecievedTempLog(_liftnum, datanow, this));
            }
            //Log.WriteInf(ConsoleColor.Yellow, "-------------------解析时间：" + (DateTime.Now - this.TimeRecieved).TotalMilliseconds);
        }

        private void ReadDataFromLog(SerialDataEventArgs e)
        {
            this.LiftInfo = e.LiftInfo;
            this.Data = e.Data;
            this.Door = e.Door;
            this.Earthquake = e.Earthquake;
            this.Estop = e.Estop;
            this.Floor = e.Floor;
            this.FloorShow = e.FloorShow;
            this.LiftNum = e.LiftNum;
            this.Run = e.Run;
            this.SerialDataRecieved = e.SerialDataRecieved;
            this.ServerData = e.ServerData;
            this.StatusCode = e.StatusCode;
            this.Stop = e.Stop;
        }

        public SerialDataEventArgs(List<byte> buffer, string type)
        {
            //this.IsRepeat = false;


            int _liftnum = -1;
            if (type == "ft")
            {
                _liftnum = buffer[0];
            }
            else
            {
                _liftnum = buffer[2];
            }

            Model.LiftInfo lift = (from r in Config.LiftInftList
                                   where r.LiftNum == _liftnum
                                   select r).FirstOrDefault();
            if (null == lift)
            {
                this.Data = null;
                return;
            }
            this.LiftInfo = lift;
            //Log.WriteInf(ConsoleColor.White, this.LiftInfo.LiftCOM + "接收:" + datanow);
            //<协议解析>
            //1.缓存数据

            #region 2.完整性判断
            //A1 C1 D_1 Len1 Len2 Len3 Data(1)…Data(m) E1 E2 E3 E4
            //S(1)…S(n) Door1 Door2 Run1 Run2 Floor1 Floor2 L1 N1 D1
            //0、A1：数据头
            //1、C1：回复代码0x03
            //2、D_1：电梯编号
            //3、Len1- Len2: data数据总字节数（Data的字节总数）,即m的值，十进制
            //5、Len3:S数据总字节数，即n的值，十进制
            //Data(1)- Data(m):数据字节,m<=300
            //E1-E4：状态代码（ASCII码）
            //S(1)-S(n):服务器窗口显示数据(ASCII,码),n<=32
            //Door1-Door2:开关门次数统计
            //Run1-Run2:运行次数统计
            //Floor1-Floor2:楼层显示(ASCII码)
            //L1:电量反馈
            //N1:预留(0x00)
            //D1：数据尾(0xD1)

            //至少要包含头（1） + 代码（1） + 电梯编号（1）+ 长度（3）
            //+ 状态（4）+ 开关门次数（2）+运行次数（2）+ 楼层（2）+ 电量（1）+ 预留（1）+ 尾（1）
            while (buffer.Count >= 19)
            {
                //2.1 查找数据头   第0--1位 数据头
                //if (buffer[0] == 0xA1 && buffer[1] == 0x03)
                //{
                //    try
                //    {
                //        //Log.WriteLog(Log.LogType.Info, "A1");
                //        string tmp = "";
                //        int index = 2;
                //        //2.2 探测缓存数据是否有一条数据的字节，如果不够，就不用费劲的做其他验证了
                //        #region 第2位：    liftnum；  描述：电梯编号
                //        int liftnum = buffer[index++];
                //        #endregion
                //        #region 第3--4位：  datalen；    描述：data数据总字节数（Data的字节总数）,即m的值
                //        int datalen = 0;
                //        datalen = int.Parse(buffer[index++].ToString("X2") + buffer[index++].ToString("X2"));
                //        #endregion
                //        #region 第5位：    slen    描述：Len3:S数据总字节数，即n的值
                //        int slen = 0;
                //        slen = int.Parse(buffer[index++].ToString("X2"));
                //        #endregion
                //        if (buffer.Count < 19 + datalen + slen) throw new Exception("数据长度不够!");
                //        #region 第5+1--datalen+5位：  data；   描述：data数据
                //        //data1
                //        this.Data = new StatusData();
                //        this.Data.Data = new List<byte>();
                //        for (int i = 0; i < datalen; i++)
                //            this.Data.Data.Add(buffer[index++]);
                //        InitData(liftnum);
                //        #endregion
                //        #region 第6+datalen--9+datalen位：stautscode；  描述：E1-E4：状态代码（ASCII码）
                //        tmp = "";
                //        tmp = Convert.ToChar(buffer[index++]).ToString();
                //        tmp += Convert.ToChar(buffer[index++]).ToString();
                //        tmp += Convert.ToChar(buffer[index++]).ToString();
                //        tmp += Convert.ToChar(buffer[index++]).ToString();
                //        string stautscode = tmp;
                //        #endregion
                //        #region 第9+1+datalen--9+datalen+slen位：  s； 描述：S(1)-S(n):服务器窗口显示数据(ASCII,码),n<=32
                //        tmp = "";
                //        for (int i = 0; i < slen; i++)
                //        {
                //            tmp += Convert.ToChar(buffer[index++]).ToString();
                //        }
                //        int s = string.IsNullOrEmpty(tmp) ? 0 : int.Parse(tmp, NumberStyles.HexNumber);
                //        #endregion
                //        #region 第10+datalen+slen--11+datalen+slen位： door；   描述：Door1-Door2:开关门次数统计
                //        tmp = "";
                //        tmp = buffer[index++].ToString("X2");
                //        tmp += buffer[index++].ToString("X2");
                //        int door = int.Parse(tmp, NumberStyles.HexNumber);
                //        #endregion
                //        #region 第12+datalen+slen--13+datalen+slen位： run；    描述：Run1-Run2:运行次数统计
                //        tmp = "";
                //        tmp = buffer[index++].ToString("X2");
                //        tmp += buffer[index++].ToString("X2");
                //        int run = int.Parse(tmp, NumberStyles.HexNumber);
                //        #endregion
                //        #region 第14+datalen+slen--15+datalen+slen位：   floornow；  描述：Floor1-Floor2:楼层显示(ASCII码)
                //        tmp = "";
                //        tmp = Convert.ToChar(buffer[index++]).ToString();
                //        tmp += Convert.ToChar(buffer[index++]).ToString();
                //        string floorshow = tmp.Trim();
                //        #endregion
                //        #region 第16+datalen+slen位：  power；  描述：L1:绝对楼层1--N
                //        int floor = 0;
                //        int floor111 = int.Parse(buffer[index++].ToString("X2"), NumberStyles.HexNumber);
                //        #endregion
                //        #region 第17+datalen+slen位：  reserve；    描述：N1:和校验位
                //        int n1 = buffer[index++];
                //        #endregion
                //        #region 第18+datalen+slen位：  end；    描述：//D1：数据尾(0xD1)
                //        int end = buffer[index++];
                //        //Log.WriteLog(Log.LogType.Info, "D1");
                //        #endregion
                //        #region 数据完整性校验；如果数据校验失败，丢弃这一包数据
                //        if (end != 0xD1)
                //        {
                //            buffer.RemoveRange(0, --index);//从缓存中删除错误数据
                //            this.Data = null;
                //            continue;//继续下一次循环
                //        }

                //        #endregion
                //        //至此，已经被找到了一条完整数据。我们将数据直接分析，或是缓存起来一起分析
                //        this.SerialDataRecieved = new List<byte>(buffer.GetRange(0, index));
                //        //buffer.RemoveRange(0, --index);//正确分析一条数据，从缓存中移除数据。
                //        buffer.Clear();
                //        #region SerialDataArgs赋值
                //        this.LiftNum = liftnum;
                //        this.StatusCode = stautscode;
                //        this.ServerData = s;
                //        this.Door = door;
                //        this.Run = run;

                //        if (0x88 == floor) floorshow = "--";
                //        else
                //        {
                //            //电梯编码格式为 绝对楼层 时取相应电梯信息中的电梯楼层信息
                //            Model.TypeLib lib = (from r in Config.TypeLibList
                //                                 where r.TypeLibNum == this.LiftInfo.TypeLibNum
                //                                 select r).FirstOrDefault();
                //            if (null != lib)
                //            {
                //                string[] strArr = this.LiftInfo.LiftActualFloor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                //                for (int i = 0; i < strArr.Length; i++)
                //                {
                //                    if (strArr[i].PadLeft(2, '0') == floorshow.PadLeft(2, '0'))
                //                    {
                //                        floor = i;
                //                        //l.FloorNow = (i + 1).ToString();// e.Floor.ToString();
                //                        break;
                //                    }
                //                }
                //                //if (lib.FloorFormat != 0)
                //                //{
                //                //string[] strArr = this.LiftInfo.LiftActualFloor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                //                //    floorshow = strArr[floor < 1 ? 0 : floor >= strArr.Length ? strArr.Length - 1 : floor - 1];
                //                //}
                //            }
                //        }
                //        //end 电梯编码格式
                //        this.FloorShow = floorshow;
                //        this.Floor = floor;
                //        #endregion
                //    }
                //    catch (Exception ex)
                //    {
                //        Log.WriteError(ex.Message, ex);
                //        Log.WriteLog(Log.LogType.Info, "解析时出错:" + buffer.ToArray().toString<byte>());
                //        this.Data = null;
                //        break;
                //        //throw ex;
                //    }
                //}
                //else 
                if (type == "ft")
                {
                    if (buffer[1] == 0x03 && buffer[2] == 0x2C)
                    {
                        if (buffer.Count < 49) throw new Exception("数据长度不够!");
                        List<byte> data = new List<byte>();
                        for (int i = 0; i < 47; i++)
                            data.Add(buffer[i]);
                        byte[] crcdata = Crc(data);
                        if (buffer[47] == crcdata[1] && buffer[48] == crcdata[0])
                        {
                            this.Data = new StatusData();
                            data.RemoveRange(0, 3);
                            this.Data.Data = data;
                            this.LiftNum = buffer[0];
                            InitFTData(data);

                            #endregion
                            //至此，已经被找到了一条完整数据。我们将数据直接分析，或是缓存起来一起分析
                            this.SerialDataRecieved = new List<byte>(buffer.GetRange(0, 49));
                            //buffer.RemoveRange(0, --index);//正确分析一条数据，从缓存中移除数据。
                            buffer.Clear();
                        }
                        else
                        {
                            buffer.RemoveRange(0, 49);//从缓存中删除错误数据
                            continue;//继续下一次循环
                        }
                    }
                    else
                    {
                        //这里是很重要的，如果数据开始不是头，则删除数据   
                        buffer.RemoveAt(0);
                    }
                }
                else
                {
                    if (buffer[0] == 0xA1 && buffer[1] == 0x03)
                    {
                        try
                        {
                            //Log.WriteLog(Log.LogType.Info, "A1");
                            string tmp = "";
                            int index = 2;
                            //2.2 探测缓存数据是否有一条数据的字节，如果不够，就不用费劲的做其他验证了
                            #region 第2位：    liftnum；  描述：电梯编号
                            int liftnum = buffer[index++];
                            #endregion
                            #region 第3--4位：  datalen；    描述：data数据总字节数（Data的字节总数）,即m的值
                            int datalen = 0;
                            datalen = int.Parse(buffer[index++].ToString("X2") + buffer[index++].ToString("X2"));
                            #endregion
                            #region 第5位：    slen    描述：Len3:S数据总字节数，即n的值
                            int slen = 0;
                            slen = int.Parse(buffer[index++].ToString("X2"));
                            #endregion
                            if (buffer.Count < 19 + datalen + slen) throw new Exception("数据长度不够!");
                            #region 第5+1--datalen+5位：  data；   描述：data数据
                            //data1
                            this.Data = new StatusData();
                            this.Data.Data = new List<byte>();
                            for (int i = 0; i < datalen; i++)
                                this.Data.Data.Add(buffer[index++]);
                            InitData(liftnum);
                            #endregion
                            #region 第6+datalen--9+datalen位：stautscode；  描述：E1-E4：状态代码（ASCII码）
                            tmp = "";
                            tmp = Convert.ToChar(buffer[index++]).ToString();
                            tmp += Convert.ToChar(buffer[index++]).ToString();
                            tmp += Convert.ToChar(buffer[index++]).ToString();
                            tmp += Convert.ToChar(buffer[index++]).ToString();
                            string stautscode = tmp;
                            #endregion
                            #region 第9+1+datalen--9+datalen+slen位：  s； 描述：S(1)-S(n):服务器窗口显示数据(ASCII,码),n<=32
                            tmp = "";
                            for (int i = 0; i < slen; i++)
                            {
                                tmp += Convert.ToChar(buffer[index++]).ToString();
                            }
                            int s = string.IsNullOrEmpty(tmp) ? 0 : int.Parse(tmp, NumberStyles.HexNumber);
                            #endregion
                            #region 第10+datalen+slen--11+datalen+slen位： door；   描述：Door1-Door2:开关门次数统计
                            tmp = "";
                            tmp = buffer[index++].ToString("X2");
                            tmp += buffer[index++].ToString("X2");
                            int door = int.Parse(tmp, NumberStyles.HexNumber);
                            #endregion
                            #region 第12+datalen+slen--13+datalen+slen位： run；    描述：Run1-Run2:运行次数统计
                            tmp = "";
                            tmp = buffer[index++].ToString("X2");
                            tmp += buffer[index++].ToString("X2");
                            int run = int.Parse(tmp, NumberStyles.HexNumber);
                            #endregion
                            #region 第14+datalen+slen--15+datalen+slen位：   floornow；  描述：Floor1-Floor2:楼层显示(ASCII码)
                            tmp = "";
                            tmp = Convert.ToChar(buffer[index++]).ToString();
                            tmp += Convert.ToChar(buffer[index++]).ToString();
                            string floorshow = tmp.Trim();
                            #endregion
                            #region 第16+datalen+slen位：  power；  描述：L1:绝对楼层1--N
                            int floor = 0;
                            int floor111 = int.Parse(buffer[index++].ToString("X2"), NumberStyles.HexNumber);
                            #endregion
                            #region 第17+datalen+slen位：  reserve；    描述：N1:和校验位
                            int n1 = buffer[index++];
                            #endregion
                            #region 第18+datalen+slen位：  end；    描述：//D1：数据尾(0xD1)
                            int end = buffer[index++];
                            //Log.WriteLog(Log.LogType.Info, "D1");
                            #endregion
                            #region 数据完整性校验；如果数据校验失败，丢弃这一包数据
                            if (end != 0xD1)
                            {
                                buffer.RemoveRange(0, --index);//从缓存中删除错误数据
                                this.Data = null;
                                continue;//继续下一次循环
                            }

                            #endregion
                            //至此，已经被找到了一条完整数据。我们将数据直接分析，或是缓存起来一起分析
                            this.SerialDataRecieved = new List<byte>(buffer.GetRange(0, index));
                            //buffer.RemoveRange(0, --index);//正确分析一条数据，从缓存中移除数据。
                            buffer.Clear();
                            #region SerialDataArgs赋值
                            this.LiftNum = liftnum;
                            this.StatusCode = stautscode;
                            this.ServerData = s;
                            this.Door = door;
                            this.Run = run;

                            if (0x88 == floor) floorshow = "--";
                            else
                            {
                                //电梯编码格式为 绝对楼层 时取相应电梯信息中的电梯楼层信息
                                Model.TypeLib lib = (from r in Config.TypeLibList
                                                     where r.TypeLibNum == this.LiftInfo.TypeLibNum
                                                     select r).FirstOrDefault();
                                if (null != lib)
                                {
                                    //string[] strArr = this.LiftInfo.LiftActualFloor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                    //for (int i = 0; i < strArr.Length; i++)
                                    //{
                                    //    if (strArr[i].PadLeft(2, '0') == floorshow.PadLeft(2, '0'))
                                    //    {
                                    //        floor = i;
                                    //        l.FloorNow = (i + 1).ToString();// e.Floor.ToString();
                                    //        break;
                                    //    }
                                    //}
                                    if (lib.FloorFormat == 1)
                                    {
                                        try
                                        {
                                            floor = Convert.ToInt32(floorshow);
                                        }
                                        catch
                                        {
                                            floor = -1;
                                        }
                                        string[] strArr = this.LiftInfo.LiftActualFloor.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                                        floorshow = strArr[floor < 1 ? 0 : floor >= strArr.Length ? strArr.Length - 1 : floor - 1];
                                    }
                                }
                            }
                            //end 电梯编码格式
                            this.FloorShow = floorshow;
                            this.Floor = floor;
                            #endregion
                        }
                        catch (Exception ex)
                        {
                            Log.WriteError(ex.Message, ex);
                            Log.WriteLog(Log.LogType.Info, "解析时出错:" + buffer.ToArray().toString<byte>());
                            this.Data = null;
                            break;
                            //throw ex;
                        }
                    }
                    else
                    {
                        //这里是很重要的，如果数据开始不是头，则删除数据   
                        buffer.RemoveAt(0);
                    }
                }
            }
        }

        public static byte[] Crc(List<byte> buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Count == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Count - start;
            int length = start + len;
            if (length > buffer.Count) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }

        private void InitData(int liftnum)
        {
            //Log.WriteLog(Log.LogType.Error, "-------------InitData--Start----解析时间：" + (DateTime.Now - this.TimeRecieved).TotalMilliseconds);
            Model.TypeLib lib = (from r in Config.TypeLibList
                                 where r.TypeLibNum == this.LiftInfo.TypeLibNum
                                 select r).FirstOrDefault();
            //Log.WriteLog(Log.LogType.Error, "-------------InitData--1----解析时间：" + (DateTime.Now - this.TimeRecieved).TotalMilliseconds);

            if (null != lib)
            {
                IEnumerable<Model.StatusPoints> points = (from r in Config.StatusPointsList
                                                          where lib.StatusPoints.Split(',').Contains(r.ID.ToString())
                                                          select r);// DAL.StatusPoints.List("ID IN(" + lib.StatusPoints + ")");
                //Log.WriteLog(Log.LogType.Error, points.Count() + "-------------InitData--2----解析时间：" + (DateTime.Now - this.TimeRecieved).TotalMilliseconds);

                this.Data.Overhaul = InitStatus(points, "检修");//检修Enum.LiftStatus.Overhaul
                if (this.LiftInfo.ShortName.ToUpper().Substring(0, 2) == "KT")
                {
                    //迅达客梯故障信号取反
                    this.Data.FaultLamp = !InitStatus(points, "故障");//故障Enum.LiftStatus.Fault
                }
                else
                {
                    this.Data.FaultLamp = InitStatus(points, "故障");//故障Enum.LiftStatus.Fault
                }

                this.Data.Rising = InitStatus(points, "上行");//上行Enum.LiftStatus.Rising
                this.Data.Descending = InitStatus(points, "下行");//下行Enum.LiftStatus.Descending
                this.Data.Dirver = InitStatus(points, "司机");//司机Enum.LiftStatus.Driver
                this.Data.OutOfService = InitStatus(points, "脱离服务");//脱离服务Enum.LiftStatus.OutOfService
                this.Data.OverLoad = InitStatus(points, "超载");//超载Enum.LiftStatus.Overload
                this.Data.StandAlone = InitStatus(points, "独立");//独立Enum.LiftStatus.Standalone
                this.Data.DoorOpen = InitStatus(points, "开门");//开门Enum.LiftStatus.DoorOpen
                this.Data.DoorOpen |= InitStatus(points, "后门开");//后门开Enum.LiftStatus.BackDoorOpen
                this.Data.DoorClose = InitStatus(points, "关门");//关门Enum.LiftStatus.DoorClose
                this.Data.DoorClose &= InitStatus(points, "后门关");//后门关Enum.LiftStatus.BackDoorClose
                this.Data.DoorLocked = InitStatus(points, "厅门锁");//厅门锁Enum.LiftStatus.DoorLocked
                this.Data.Locked = InitStatus(points, "锁梯");//锁梯Enum.LiftStatus.Locked
                this.Data.ConverterAlarm = InitStatus(points, "变频器报警");//变频器报警Enum.LiftStatus.ConverterAlarm
                this.Data.CageAlarm = InitStatus(points, "轿厢报警");//轿厢报警Enum.LiftStatus.CageAlarm
                this.Data.Power = InitStatus(points, "电梯电源");//电梯电源Enum.LiftStatus.Power
                this.Data.MainPower = InitStatus(points, "主控制柜电源");//主控制柜电源Enum.LiftStatus.Mainpower
                this.Data.FireReturn = InitStatus(points, "火警返回");//火警返回Enum.LiftStatus.FireReturn
                this.Data.Fire = InitStatus(points, "消防");//消防Enum.LiftStatus.Fire
                this.Data.EPS = InitStatus(points, "应急电源");//应急电源Enum.LiftStatus.EPS
                this.Data.UDF1 = InitStatus(points, "采样点0");//自定义输入1/采样点0 Enum.LiftStatus.UDF1
                this.Data.UDF2 = InitStatus(points, "采样点1");//自定义输入2、采样点1 Enum.LiftStatus.UDF2
                this.Data.UDF3 = InitStatus(points, "采样点2");//自定义输入3/采样点2 Enum.LiftStatus.UDF3
                this.Data.Local = InitStatus(points, "本地控制");//本地控制 Enum.LiftStatus.Local 
                this.Data.Remote = InitStatus(points, "远程控制");//远程控制 Enum.LiftStatus.Remote
                this.Data.Peak = InitStatus(points, "高峰运行");//高峰运行Enum.LiftStatus.Peak
                this.Earthquake = InitStatus(points, "地震");//地震Enum.LiftStatus.Earthquake
                this.Data.IsEarthquaked = InitStatus(points, "地震控制返回");//地震控制返回Enum.LiftStatus.IsEarthquaked
                this.Data.IsEarthquaked = this.Data.IsEarthquaked || this.Earthquake;

                if (this.LiftInfo.LiftType == (int)Enum.LiftType.电梯)
                {
                    //以下为电梯独有
                    this.Data.CageLocked = InitStatus(points, "轿门锁");//轿门锁Enum.LiftStatus.CageLocked
                    this.Data.RemoteLocked = InitStatus(points, "锁梯控制");//远程锁梯控制返回/锁梯控制Enum.LiftStatus.RemoteLocked
                    this.Data.UDF1Return = InitStatus(points, "自定义控制1返回");//自定义控制1返回Enum.LiftStatus.UDF1Return
                    this.Data.UDF2Return = InitStatus(points, "自定义控制2返回");//自定义控制2返回Enum.LiftStatus.UDF2Return
                    this.Data.UDF3Return = InitStatus(points, "自定义控制3返回");//自定义控制3返回Enum.LiftStatus.UDF3Return

                    this.Data.InnerRing = InitRing(7);//第七位开始-22
                    this.Data.OuterUpRing = InitRing(23);//22-38
                    this.Data.OuterDownRing = InitRing(39);//38-54
                }
                else
                {
                    //以下为扶梯及人行步道独有
                    this.Stop = InitStatus(points, "停止");//停止Enum.LiftStatus.Stop
                    this.Estop = InitStatus(points, "急停");//急停Enum.LiftStatus.Estop
                    this.Data.DisContinuous = InitStatus(points, "断续运行");//断续运行Enum.LiftStatus.DisContinuous
                    this.Data.Continuous = !InitStatus(points, "连续运行");//连续运行Enum.LiftStatus.Continuous
                }
            }
            //Log.WriteLog(Log.LogType.Error, "-------------------InitData：" + (DateTime.Now - this.TimeRecieved).TotalMilliseconds);
        }

        private void InitFTData(List<byte> data)
        {
            string msg = string.Empty;
            this.Estop = Convert.ToString(data[43], 2).PadLeft(8, '0').Substring(1, 1) == "1" ? true : false;
            this.Data.FaultLamp = Convert.ToString(data[41], 2).PadLeft(8, '0').Substring(2, 1) == "1" ? true : false;
            this.Data.Standby = Convert.ToString(data[41], 2).PadLeft(8, '0').Substring(6, 1) == "1" ? true : false;
            this.Data.Descending = Convert.ToString(data[41], 2).PadLeft(8, '0').Substring(0, 1) == "1" ? true : false;
            this.Data.Rising = Convert.ToString(data[41], 2).PadLeft(8, '0').Substring(1, 1) == "1" ? true : false;
            this.Data.Overhaul = Convert.ToString(data[40], 2).PadLeft(8, '0').Substring(7, 1) == "1" ? true : false;
            this.FloorShow = "";
            this.Standby = Convert.ToString(data[41], 2).PadLeft(8, '0').Substring(6, 1) == "1" ? true : false;

            string fault_40001 = Convert.ToString(data[0], 2).PadLeft(8, '0') + Convert.ToString(data[1], 2).PadLeft(8, '0');
            for (int i = 1; i < 16; i++)
            {
                if (fault_40001.Substring(15 - i, 1) == "1")
                {
                    msg += "E0" + i.ToString("X") + ";";
                }
            }
            string fault_40002 = Convert.ToString(data[2], 2).PadLeft(8, '0') + Convert.ToString(data[3], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40002.Substring(15 - i, 1) == "1")
                {
                    msg += "E1" + i.ToString("X") + ";";
                }
            }
            string fault_40003 = Convert.ToString(data[4], 2).PadLeft(8, '0') + Convert.ToString(data[5], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40003.Substring(15 - i, 1) == "1")
                {
                    msg += "E2" + i.ToString("X") + ";";
                }
            }
            string fault_40004 = Convert.ToString(data[6], 2).PadLeft(8, '0') + Convert.ToString(data[7], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40004.Substring(15 - i, 1) == "1")
                {
                    msg += "E3" + i.ToString("X") + ";";
                }
            }
            string fault_40005 = Convert.ToString(data[8], 2).PadLeft(8, '0') + Convert.ToString(data[9], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40005.Substring(15 - i, 1) == "1")
                {
                    msg += "E4" + i.ToString("X") + ";";
                }
            }
            string fault_40006 = Convert.ToString(data[10], 2).PadLeft(8, '0') + Convert.ToString(data[11], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40006.Substring(15 - i, 1) == "1")
                {
                    msg += "E5" + i.ToString("X") + ";";
                }
            }
            string fault_40007 = Convert.ToString(data[12], 2).PadLeft(8, '0') + Convert.ToString(data[13], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40007.Substring(15 - i, 1) == "1")
                {
                    msg += "E6" + i.ToString("X") + ";";
                }
            }
            string fault_40008 = Convert.ToString(data[14], 2).PadLeft(8, '0') + Convert.ToString(data[15], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40008.Substring(15 - i, 1) == "1")
                {
                    msg += "E7" + i.ToString("X") + ";";
                }
            }
            string fault_40009 = Convert.ToString(data[16], 2).PadLeft(8, '0') + Convert.ToString(data[17], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40009.Substring(15 - i, 1) == "1")
                {
                    msg += "E8" + i.ToString("X") + ";";
                }
            }
            string fault_40010 = Convert.ToString(data[18], 2).PadLeft(8, '0') + Convert.ToString(data[19], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40010.Substring(15 - i, 1) == "1")
                {
                    msg += "E9" + i.ToString("X") + ";";
                }
            }
            string fault_40011 = Convert.ToString(data[20], 2).PadLeft(8, '0') + Convert.ToString(data[21], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40011.Substring(15 - i, 1) == "1")
                {
                    msg += "EA" + i.ToString("X") + ";";
                }
            }
            string fault_40012 = Convert.ToString(data[22], 2).PadLeft(8, '0') + Convert.ToString(data[23], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40012.Substring(15 - i, 1) == "1")
                {
                    msg += "EB" + i.ToString("X") + ";";
                }
            }
            string fault_40013 = Convert.ToString(data[24], 2).PadLeft(8, '0') + Convert.ToString(data[25], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40013.Substring(15 - i, 1) == "1")
                {
                    msg += "EC" + i.ToString("X") + ";";
                }
            }
            string fault_40014 = Convert.ToString(data[26], 2).PadLeft(8, '0') + Convert.ToString(data[27], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40014.Substring(15 - i, 1) == "1")
                {
                    msg += "ED" + i.ToString("X") + ";";
                }
            }
            string fault_40015 = Convert.ToString(data[28], 2).PadLeft(8, '0') + Convert.ToString(data[29], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40015.Substring(15 - i, 1) == "1")
                {
                    msg += "EE" + i.ToString("X") + ";";
                }
            }
            string fault_40016 = Convert.ToString(data[30], 2).PadLeft(8, '0') + Convert.ToString(data[31], 2).PadLeft(8, '0');
            for (int i = 0; i < 16; i++)
            {
                if (fault_40016.Substring(15 - i, 1) == "1")
                {
                    msg += "EF" + i.ToString("X") + ";";
                }
            }
            if (!string.IsNullOrEmpty(msg))
            {
                this.Data.FaultCode = "故障代码:" + msg.Substring(0, msg.Length - 1);
            }
            else
            {
                this.Data.FaultCode = "";
            }
        }

        private bool InitStatus(IEnumerable<Model.StatusPoints> points, string sn)
        {
            Model.LiftStatus s = (from r in Config.StatusList
                                  where r.LiftStatusName == sn
                                  select r).FirstOrDefault();
            if (null == s)
                s = (from r in Config.StatusList
                     where r.LiftStatusName.Contains(sn)
                     select r).FirstOrDefault();
            if (null == s) return false;

            Model.StatusPoints p = (from r in points
                                    where r.LiftStatusNum == s.LiftStatusNum
                                    select r).FirstOrDefault();
            if (null != p)
            {
                int index = p.StatusByte.toNumeric() - 1;
                int bit = p.StatusBit.toNumeric() - 1;
                if (this.Data.Data.Count <= index) return false;
                string tmp = Convert.ToString(this.Data.Data[index], 2);
                tmp = tmp.Insert(0, new string('0', 8 - tmp.Length)).Reverse();
                char[] c = tmp.ToCharArray();

                bool lowBit = false;
                if (s.LiftStatusName.ToUpper().StartsWith("L")) lowBit = true;

                if (lowBit)
                {
                    if (c[bit] != '0')
                        return false;
                    else
                        return true;
                }
                else
                {
                    if (c[bit] != '0')
                        return true;
                    else
                        return false;
                }
            }
            return false;
        }

        private List<int> InitRing(int index)
        {
            List<int> list = new List<int>();
            string tmp = "";
            index--;
            for (int i = 0; i < 16; i++)
            {
                if (this.Data.Data.Count <= index) break;
                tmp += Convert.ToString(this.Data.Data[index++], 2).Right(4, '0').Reverse();
            }
            char[] c = tmp.ToCharArray();
            int floor = -1;
            do
            {
                floor++;
                floor = Array.IndexOf(c, '1', floor);
                if (floor != -1) list.Add(floor + 1);
            } while (floor != -1);
            return list;
        }
    }

    /// <summary>
    /// Data数据实例
    /// 所有bool值;true有效,false无效
    /// </summary>
    public class StatusData
    {
        public List<byte> Data { get; set; }
        /// <summary>
        /// 司机开关;true有效,false无效
        /// </summary>
        public bool Dirver { get; set; }

        /// <summary>
        /// 关轿厢照明;true有效,false无效
        /// </summary>
        public bool CloseLighting { get; set; }

        /// <summary>
        /// 上行;true有效,false无效
        /// </summary>
        public bool Rising { get; set; }

        /// <summary>
        /// 下行;true有效,false无效
        /// </summary>
        public bool Descending { get; set; }

        /// <summary>
        /// 电梯故障指示灯;true有效,false无效
        /// </summary>
        public bool FaultLamp { get; set; }

        /// <summary>
        /// 检修;true有效,false无效
        /// </summary>
        public bool Overhaul { get; set; }

        /// <summary>
        /// 轿内优先(独立);true有效,false无效
        /// </summary>
        public bool StandAlone { get; set; }

        /// <summary>
        /// 超载;true有效,false无效
        /// </summary>
        public bool OverLoad { get; set; }

        /// <summary>
        /// 脱离服务;true有效,false无效
        /// </summary>
        public bool OutOfService { get; set; }

        /// <summary>
        /// 开门;true有效,false无效
        /// </summary>
        public bool DoorOpen { get; set; }

        /// <summary>
        /// 关门;true有效,false无效
        /// </summary>
        public bool DoorClose { get; set; }

        /// <summary>
        /// 消防返基;true有效,false无效
        /// </summary>
        public bool Fire { get; set; }

        /// <summary>
        /// 轿厢锁
        /// </summary>
        public bool CageLocked { get; set; }

        /// <summary>
        /// 厅门锁;true有效,false无效
        /// </summary>
        public bool DoorLocked { get; set; }

        /// <summary>
        /// 应急电源;true有效,false无效
        /// </summary>
        public bool EPS { get; set; }

        /// <summary>
        /// 主控制柜电源;true有效,false无效
        /// </summary>
        public bool MainPower { get; set; }

        /// <summary>
        /// 电梯电源;true有效,false无效
        /// </summary>
        public bool Power { get; set; }

        /// <summary>
        /// 火警返回;true有效,false无效
        /// </summary>
        public bool FireReturn { get; set; }

        /// <summary>
        /// 轿厢报警;true有效,false无效
        /// </summary>
        public bool CageAlarm { get; set; }

        /// <summary>
        /// 变频器报警;true有效,false无效
        /// </summary>
        public bool ConverterAlarm { get; set; }

        /// <summary>
        /// 锁梯;true有效,false无效
        /// </summary>
        public bool Locked { get; set; }

        /// <summary>
        /// true本地
        /// </summary>
        public bool Local { get; set; }

        /// <summary>
        /// true远程
        /// </summary>
        public bool Remote { get; set; }

        /// <summary>
        /// 断续运行
        /// </summary>
        public bool DisContinuous { get; set; }

        /// <summary>
        /// 连续运行
        /// </summary>
        public bool Continuous { get; set; }

        /// <summary>
        /// 高峰运行;true有效,false无效
        /// </summary>
        public bool Peak { get; set; }

        /// <summary>
        /// 远程锁梯控制返回
        /// </summary>
        public bool RemoteLocked { get; set; }
        /// <summary>
        /// 地震控制返回
        /// </summary>
        public bool IsEarthquaked { get; set; }
        /// <summary>
        /// 自定义控制1返回
        /// </summary>
        public bool UDF1Return { get; set; }
        /// <summary>
        /// 自定义控制2返回
        /// </summary>
        public bool UDF2Return { get; set; }
        /// <summary>
        /// 自定义控制3返回
        /// </summary>
        public bool UDF3Return { get; set; }
        /// <summary>
        /// 轿内召唤楼层(相对)
        /// </summary>
        public List<int> InnerRing { get; set; }

        /// <summary>
        /// 上召唤楼层(相对)
        /// </summary>
        public List<int> OuterUpRing { get; set; }

        /// <summary>
        /// 下召唤楼层(相对)
        /// </summary>
        public List<int> OuterDownRing { get; set; }

        /// <summary>
        /// 自定义输入1
        /// </summary>
        public bool UDF1 { get; set; }

        /// <summary>
        /// 自定义输入2
        /// </summary>
        public bool UDF2 { get; set; }

        /// <summary>
        /// 自定义输入3
        /// </summary>
        public bool UDF3 { get; set; }


        public bool Standby { get; set; }
        public string FaultCode { get; set; }
    }

    public class SameDataEventArgs : EventArgs
    {
        public SameDataEventArgs(byte b)
        {
            _liftnum = b;
        }
        private int _liftnum;
        public int LiftNum { get { return _liftnum; } }
    }
}
